#0  rarray.append(Rapameter("tau",  "Transcription-translation delay",    10.0,True,True,0.1));
#1  rarray.append(Rapameter("rp",   "Production rate (P)",                1.9,True,True,0.1));
#2  rarray.append(Rapameter("rm",   "Production rate (M)",                0.5,True,True,0.1));
#3  rarray.append(Rapameter("qp",   "Degradation rate (P)",               0.4,True,True,0.1));
#4  rarray.append(Rapameter("qm",   "Degradation rate (M)",               0.4,True,True,0.1));
#5  rarray.append(Rapameter("m",    "Non-linearity",                      3.5,True,True,0.1));
#6  rarray.append(Rapameter("n",    "Hill coefficient",                   6.0,True,True,2.1));
#7  rarray.append(Rapameter("k",    "Scaling constant",                   1.0,True,True,0.1));
#   [10.0,1.9,0.5,0.4,0.4,3.5,6.0,1.0]

from pylab import *
from rapameters import *
from oscillator_hash import *
from copy import *
from time import *
from raptools import *
from wave import Wave
from random import *;

if len(sys.argv) < 2:
  print "usage: rap.py amp wl"
  quit()

 #PARAMETRI
AMP = float(sys.argv[1]) 
WL = float(sys.argv[2]) 
  
#OSCILATORJI
OSC_LIFETIME        = 3
SAMPLING_EXP        = 1
TIME                = int(math.ceil(WL*50));
DT                  = 1*10**(-SAMPLING_EXP);

#ZACETNI KORAK IN NAPAKA
STEP    = 0
AMP_MAX  = AMP*10
EPS_AMP = 0.01
EPS_FRQ = 0.01
EPS_TIM = 5


#POPULACIJA
POPULATION          = [];
POP_MAX             = 15;
POP_LIFETIME        = 50;
POP_SIZE            = 5;
POP_SIZES = []

#VERJETNOSTI
#             [tau, rp,   rm, qp, qm, m,  n,  k]
RECOMBINATION   = 1.0/15.0;
MUTATION_MASK   = [1,1,1,1,1,1,1,1]
#MUTATION_MASK   = [1,1,1,1,1,0,0,0]
#MUTATION_MASK    = [1,0,0,0,0,0,0,0]
MUTATION_CUT    = 0.01
MUTATION        = 1.0/sum(MUTATION_MASK);
#MUTATION        = 1.0


print "Time: ", TIME, " h"
print "Resolution: ", DT, "h"
print "----------------------------------------------------------"


#             [tau, rp,   rm, qp, qm, m,  n,  k]
#rarray        = [1.0 for i in range(8)];

#STEP 1
#rarray        = [1.0,1.0,1.0,1.0,1.0,3.0,2.0,1.0];


#STEP 2
#rarray        = [2.056095470877644, 1.7842645441679132, 3.1406046970462609, 1.0, 0.81388424761450151, 3.0, 2.0, 1.0]
#rarray        = [14.086367508237171, 1.7842645441679132, 3.1406046970462609, 1.0, 0.81388424761450151, 3.0, 2.0, 1.0]
#rarray        = [21.037872396501783, 1.7842645441679132, 3.1406046970462609, 1.0, 0.81388424761450151, 3.0, 2.0, 1.0]
#rarray        = [35.098682419975916, 1.7842645441679132, 3.1406046970462609, 1.0, 0.81388424761450151, 3.0, 2.0, 1.0]
#rarray        = [44.743915114835517, 1.7842645441679132, 3.1406046970462609, 1.0, 0.81388424761450151, 3.0, 2.0, 1.0]

#rarray = [0.12356914204038405, 2.1805694915326734, 3.0119072037051589, 1.0988076894630026, 0.78640460178021654, 3.0, 2.0, 1.0]
#rarray = [0.16359362901765573, 2.1805694915326734, 3.0119072037051589, 1.0988076894630026, 0.78640460178021654, 3.0, 2.0, 1.0]
#rarray = [0.74465479035970428, 2.1805694915326734, 3.0119072037051589, 1.0988076894630026, 0.78640460178021654, 3.0, 2.0, 1.0]


#STEP 3
#rarray        = [48.014503111997946, 1.7842645441679132, 3.1406046970462609, 1.0, 0.81388424761450151, 3.0, 2.0, 1.0]
rarray		= [4.0,1.0,1.0,0.21,0.21,3.0,2.0,1.0]


#Starting oscillator
WAVE          = Wave(float(sys.argv[1]),1.0/float(sys.argv[2]),TIME,DT)
start         = Oscillator(rarray,TIME,DT,ROUNDING, AMP_MAX)

POPULATION    = [ Oscillator( gen_osc_repr(start, MUTATION, MUTATION_MASK), TIME, DT, ROUNDING, AMP_MAX) for i in range(POP_SIZE)]

POP_STEP = 0

#zacetni oscilator
figure(1)
spt = start.get_times();
spv = start.get_vals();
#plot(spt, spv, linewidth=1.0, color = 'blue')
#show();
#quit()

cmnbest     = float("inf");
cmnworst    = 0;
oscbest     = None
oscworst    = None
cut         = 0;


 

ca = False
cf = False
cs = False

#Zanka skozi generacije
#figure(1)
#for GEN in range(POP_LIFETIME):
while not (ca and cf and cs):


  POP_STEP = POP_STEP + 1

  #print "#GENERATION (",str(GEN),")#, size: ", len(POPULATION)
  print "#GENERATION (",str(POP_STEP),")#, size: ", len(POPULATION)
  NEW_POPULATION = []
  POP_SIZES = POP_SIZES + [len(POPULATION)]

  
  #######################
  #KRITERIJ ZA PREZIVETJE
  #######################

  mn_list = []
  for osc in POPULATION:
    c = cmp_wav_osc_fitness(WAVE, osc)
    if c < float("inf"):
      mn_list = mn_list + [c];
    cut = mean(mn_list);  
  
  #Prepolovitev populacije
  if len(POPULATION) > POP_MAX:
    #print "Half"
    cut = median(mn_list)
    
  ##########
  #SELEKCIJA
  ##########
  cmnbest     = float("inf");
  cmnworst    = 0;
  for osc in POPULATION:

    cmn = cmp_wav_osc_fitness(WAVE, osc);

    #print id(osc), str(osc)
    #print id(osc), 'compare ', cmp_wav_osc_lst(WAVE, osc), 'mean', cmn
    #print id(osc), 'makes the cut(',str(cut),')? ', cmn <= cut;
    #print ''

    ####
    #CUT
    ####
    '''
    if cmn <= cut:
      if cmn < cmnbest:
        cmnbest = cmn;
        oscbest = osc;
      if cmn >= cmnworst:
        cmnworst = cmn;
      
      NEW_POPULATION = NEW_POPULATION + [osc]
      if size(NEW_POPULATION) > POP_MAX:
        print 'remove'
        NEW_POPULATION.remove(cmnworst)
    '''
    
    '''
    if cmn < cmnbest:
        cmnbest = cmn;
        oscbest = osc;
    if cmn >= cmnworst:
        cmnworst = cmn;
        oscworst = osc;
      
    NEW_POPULATION = NEW_POPULATION + [osc]
    if size(NEW_POPULATION) > POP_MAX:
        NEW_POPULATION.remove(oscworst)
        for onp in NEW_POPULATION:
            cmnworst = 0
            cmnnp = cmp_wav_osc_fitness(WAVE, onp);
            if cmn >= cmnworst:
                cmnworst = cmnnp;
                oscworst = onp;
    '''
    if cmn <= cut:
        if cmn < cmnbest:
            cmnbest = cmn;
            oscbest = osc;
        if cmn >= cmnworst:
            cmnworst = cmn;
            oscworst = osc;
      
        NEW_POPULATION = NEW_POPULATION + [osc]
        if size(NEW_POPULATION) > POP_MAX:
            NEW_POPULATION.remove(oscworst)
            for onp in NEW_POPULATION:
                cmnworst = 0
                cmnnp = cmp_wav_osc_fitness(WAVE, onp);
                if cmn >= cmnworst:
                    cmnworst = cmnnp;
                    oscworst = onp;
    #########
    #DBGPLOT#
    #########
    #t = oscbest.get_times();
    #v = oscbest.get_vals();
    #plot(t,v,color=str(clr))
  
  #print 'before repr: ', len(NEW_POPULATION)

  ##############################
  #POPRAVLJANJE MUTACIJSKE MASKE
  ##############################  
  '''  
  if math.fabs(oscbest.get_amp()-float(sys.argv[1]))/float(sys.argv[1])  <= MUTATION_CUT:
    print 'MUTATION CUT'
    MUTATION_MASK = [1,0,0,0,0,0,0,0]
    MUTATION = 1.0
  else:
    MUTATION_MASK = [1,1,1,1,1,1,1,1]
    MUTATION = 1.0/8.0
  '''
  
  #########################
  #REPRODUKCIJA IN MUTACIJE
  #########################
  
  #off_size = 1+len(NEW_POPULATION)/2;
  off_size = 1+len(NEW_POPULATION);
  fitness_isum = sum([1.0/cmp_wav_osc_fitness(WAVE, osc) for osc in NEW_POPULATION])
  off_list = [[id(osc), osc, math.floor((1.0/cmp_wav_osc_fitness(WAVE, osc))/fitness_isum*off_size)] for osc in NEW_POPULATION]
  
  #print off_list
  #quit()
  
  for osc_repr in off_list:
    try:
      for i in range(int(osc_repr[2])):
        NEW_POPULATION = NEW_POPULATION + [ Oscillator( gen_osc_repr(osc_repr[1], MUTATION, MUTATION_MASK), TIME, DT, ROUNDING, AMP_MAX) ]
    except ValueError:
      print osc_repr[1]
      print osc_repr[2]
      continue
  
  ca = math.fabs(oscbest.get_amp()*1/EPS_AMP-WAVE.get_amp()*1/EPS_AMP)                  < 1
  cf = math.fabs(oscbest.get_frq()*1/EPS_AMP-WAVE.get_frq()*1/EPS_AMP)                  < 1
  cs = math.fabs(oscbest.get_tim_up()*1/EPS_TIM-oscbest.get_tim_down()*1/EPS_TIM)       < 1
  
  #print off_list
  #print
  #print
  #print
  #print NEW_POPULATION
  print "----------------------------------------------------------"
  print 'WAVE (RED)'
  print "----------------------------------------------------------"
  print 'amp: ',WAVE.get_amp();
  print 'frq: ', WAVE.get_frq();
  print 'time up: ',WAVE.get_tim_up();
  print 'time down: ',WAVE.get_tim_down();
  print "----------------------------------------------------------"
  print 'OSCILLATOR : CURRENT BEST', id(oscbest), ' (BLUE)'
  print "----------------------------------------------------------"
  print 'amp: ',oscbest.get_amp();
  print 'frq: ', oscbest.get_frq();
  print 'time up: ',oscbest.get_tim_up();
  print 'time down: ',oscbest.get_tim_down();
  print 'parameters', oscbest.get_rapams();
  print ""
  
  POPULATION = NEW_POPULATION;
  
  

  



print "----------------------------------------------------------"
print 'WAVE (RED)'
print "----------------------------------------------------------"
print 'amp: ',WAVE.get_amp();
print 'frq: ', WAVE.get_frq();
print 'time up: ',WAVE.get_tim_up();
print 'time down: ',WAVE.get_tim_down();
print "----------------------------------------------------------"
print 'OSCILLATOR : CURRENT BEST', id(oscbest), ' (BLUE)'
print "----------------------------------------------------------"
print 'amp: ',oscbest.get_amp();
print 'frq: ', oscbest.get_frq();
print 'time up: ',oscbest.get_tim_up();
print 'time down: ',oscbest.get_tim_down();
print 'parameters', oscbest.get_rapams();
print ""


#print "----------------------------------------------------------"
#print 'ALIVE:'
#print "----------------------------------------------------------"
#print POPULATION
#print ""

fnamet = time()

figure(1)
t = oscbest.get_times();
v1 =  oscbest.get_vals();
v2 = WAVE.get_vals();
plot(t, v1, linewidth=1.0, color = 'blue')
plot(t, v2, linewidth=1.0, color = 'red')
xlabel('time')
ylabel('vals')
xticks(range(0,TIME,int(TIME*0.1)))
title(str(oscbest))
grid(True)
savefig('out/rap11/'+str(fnamet)+'rap.png',format='png')      

figure(2)
plot(range(len(POP_SIZES)), POP_SIZES, linewidth=1.0, color = 'blue')
savefig('out/rap11/'+str(fnamet)+'pop.png',format='png')      

print "Steps: ",POP_STEP 
print "End."
